package Organisation;

import java.util.Random;
import java.util.StringTokenizer;
import java.util.ArrayList;

import Environnement.Chemin;
import Environnement.Graph;
import Environnement.Percepts;
import Environnement.Util;
import Environnement.Noeud;
import Environnement.Arete;
import Organisation.AgentBase;
import Saboteur.AgentSab;
import eis.exceptions.ActException;
import eis.iilang.Action;
import jade.core.AID;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;

/**
 * TODO description
 */
public class BehaviourSab2 extends Behaviour {

	String target;
	
	public BehaviourSab2()
	{

	}

	@Override
	public void action() 
	{
		try{
	
			AgentBase agent = (AgentBase)getAgent();
			Percepts p = agent.getPercepts("lastActionResult");
			boolean attaque = false;
			
			if(p.getValues().get(0).equals("failed_resources"))
			{
				if(agent.isVerbose())
					agent.println("Energie insuffisante -> Recharge");
				agent.performAction(Util.rechargeAction());
				return;
			}
			checkPercept();
			checkMessage();
			checkHealth();
			checkTarget();
			
			Action act =  pursueTarget();
			if(act != null)
			{
				agent.performAction(act);
				return;
			}
			String pos = walk();
			if(agent.isVerbose())
				agent.println("Deplacement aleatoire");
			agent.performAction(Util.gotoAction(pos));
		}
		catch(ActException e)
		{
			System.out.println("Erreur : "+e.getMessage());
		}
		
	}
	
	@Override
	public boolean done() {
		// TODO Auto-generated method stub
		
		return false;
	}
	
	public void checkTarget()
	{
		AgentBase agent = (AgentBase)getAgent();
		Chemin road = ((AgentSab)agent).getChemin();
		
		if(agent.getPercepts("visibleEntity")!= null)
		{
			boolean newTarget = (target==null);
			ArrayList<String> targets = agent.getPercepts("visibleEntity").getValues();
			for(int i = 0; i< targets.size();i++) 
			{
				StringTokenizer tk =  new StringTokenizer(targets.get(i));
					
				String name = tk.nextToken();
				tk.nextToken();
				String team = tk.nextToken();
				String state = tk.nextToken();
				if(newTarget)
				{
					if(! agent.getTeamName().equals(team) && !state.equals("disabled"))
					{	
						target = name;
						if(agent.isVerbose())
							agent.println("Nouvelle cible trouvée "+name);
						agent.addGoal("target "+name);
						break;
					}
				}
				else if(name.equals(target) && ! agent.getTeamName().equals(team))
				{
					if(state.equals("disabled"))
					{
						if(agent.isVerbose())
							agent.println("Cible desactivé");
						agent.removeGoal("target "+target);
						target = null;
						road = null;
						i = 0;
					}
					
				}
			}
		}
	}
	
	public void checkMessage()
	{
		AgentSab agent = (AgentSab)getAgent();
		Graph graph = agent.getGraph();
		ACLMessage msg = agent.receive();
		Chemin road = agent.getChemin();
		while(msg != null)
		{
			String id = msg.getConversationId();
			if(id.equals("Noeud"))
			{
				StringTokenizer tk = new StringTokenizer(msg.getContent());
				
				String s1= tk.nextToken();
				String s2 = tk.nextToken();
				
				Noeud n1 = null;
				Noeud n2 = null;
				
				if(!graph.isPresent(s1))
				{
					n1 = new Noeud(s1);
					graph.addNoeud(n1);
				}
				else
					n1 = graph.getNoeud(s1);
				
				boolean find = false;
				
				for(Arete a: n1.getAretes())
					if(a.getArrive().getName().equals(s2))
					{
						find = true;
						break;
					}
				
				if(!find)
				{
					if(agent.isVerbose())
						agent.println("  Add Noeud --> "+msg.getContent());
					if(!graph.isPresent(s2))
					{
						n2 = new Noeud(s2);
						n1.addNoeud(n2,1);
						graph.addNoeud(n2);
					}
					else
						n1.addNoeud(graph.getNoeud(s2),1);
				}
			}
			else if(id.equals("Target"))
			{
				String pos = agent.getPercepts("position").getValues().get(0);
				if(target != null)
					continue;
				StringTokenizer tk = new StringTokenizer(msg.getContent());
				String tmp = tk.nextToken();
				String dst = tk.nextToken();
					if((road = graph.pathTo(pos,dst)) != null)
					{
						((AgentSab)agent).setChemin(road);
						target =msg.getContent();
						agent.addGoal("target "+target);
						continue;
					}
			}
			else if(id.equals("Update"))
			{
				StringTokenizer tk = new StringTokenizer(msg.getContent());
				
				String s1= tk.nextToken();
				String s2 = tk.nextToken();
				int poids = Integer.parseInt(tk.nextToken());
				
				Noeud n1 = null;
				Noeud n2 = null;
				
				if(!graph.isPresent(s1))
				{
					n1 = new Noeud(s1);
					graph.addNoeud(n1);
				}
				else
					n1 = graph.getNoeud(s1);
				boolean find = false;
				
				for(Arete a: n1.getAretes())
					if(a.getArrive().getName().equals(s2))
					{
						find = true;
						break;
					}
				
				if(!find)
				{
					if(agent.isVerbose())
						agent.println("  Add Noeud --> "+msg.getContent());
					if(!graph.isPresent(s2))
					{
						n2 = new Noeud(s2);
						n1.addNoeud(n2,1);
						graph.addNoeud(n2);
					}
					else
						n1.addNoeud(graph.getNoeud(s2),1);
				}
				Arete a1 = null;
				for(Arete a: n1.getAretes())
					if(a.getArrive().getName().equals(s2))
					{
						a1 =a;
					}
				a1.setPoids(poids);
			}
			msg = agent.receive();
		}
		
	}
	
	public void checkHealth()
	{
		AgentBase agent = (AgentBase)getAgent();
		String enr = agent.getPercepts("health").getValues().get(0);
		String maxEnr = agent.getPercepts("maxHealth").getValues().get(0);
		if(!enr.equals(maxEnr))
		{	
			ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
			msg.setConversationId("Repair");
			msg.setContent(agent.getName());
			AID[] receiver =agent.getTeamAID(); 
			for(int i = 0; i<receiver.length;i++)
				msg.addReceiver(receiver[i]);
			agent.send(msg);
		}
		else
		{
			ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
			msg.setConversationId("Repaired");
			msg.setContent(agent.getName());
			AID[] receiver =agent.getTeamAID(); 
			for(int i = 0; i<receiver.length;i++)
				msg.addReceiver(receiver[i]);
			agent.send(msg);
		}
	}
	
	public void checkPercept()
	{
			String position = null;
			
			AgentBase agent = (AgentBase)getAgent();
			Graph graph = ((AgentSab)agent).getGraph();
			for ( Percepts p : agent.getAllPercept() ) 
			{	
				if ( p.getName().equals("position") ) 
				{
					
					position = p.getValues().get(0);
					agent.removeBelief("position");
					
					agent.addBelief("position",position);
					
				}
				else if ( p.getName().equals("visibleEdge") ) 
				{	
					for(String s : p.getValues())
					{
						StringTokenizer tk = new StringTokenizer(s);
						String vertex1 = tk.nextToken();
						String vertex2 = tk.nextToken();
						Noeud ver1, ver2;
						
						if(!graph.isPresent(vertex1))
						{
							ver1 = new Noeud(vertex1);
							graph.addNoeud(ver1);
							
						}
						else
						{
							ver1 = graph.getNoeud(vertex1);
						}
						if(!graph.isPresent(vertex2))
						{
							ver2 = new Noeud(vertex2);
							graph.addNoeud(ver2);
						}
						else
						{
							ver2 = graph.getNoeud(vertex2);
						}		
						
						boolean add = false;
						
						for(Arete a : ver1.getAretes())
						{
							if(a.getArrive() == ver2 )
								add = true;
						}
						
						if(add == false)
						{
							ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
							msg.setConversationId("Noeud");
							msg.setContent(vertex1+" "+vertex2+" Vis");
							AID[] receiver =agent.getTeamAID(); 
							for(int i = 0; i<receiver.length;i++)
								msg.addReceiver(receiver[i]);
							ver1.addNoeud(ver2, 1);
							agent.send(msg);
						}
					}
					
				}
		}
	}

	private String walk() {

		AgentBase agent = (AgentBase)getAgent();
		
		Percepts p = agent.getPercepts("visibleEdge");
		String position = agent.getPercepts("position").getValues().get(0);
		
		Random rand = new Random(System.currentTimeMillis());
		String dest = null;
		boolean cont = false;
		while( !cont)
		{
			int i = Math.abs(rand.nextInt())% p.getValues().size();
			StringTokenizer tk = new StringTokenizer(p.getValues().get(i));
			String n1 = tk.nextToken();
			String n2= tk.nextToken();
			if(n1.equals(position))
			{
				dest = n2;
				cont = true;
			}
			else if(n2.equals(position))
			{
				dest = n1;
				cont = true;
			}
		}	
		return dest;
		
	}

	public Action pursueTarget()
	{
		AgentBase agent = (AgentBase)getAgent();
		String pos = agent.getPercepts("position").getValues().get(0);
		Graph graph = ((AgentSab)agent).getGraph();
		Chemin road = ((AgentSab)agent).getChemin();
		if(target != null)
		{
			Percepts p = ((AgentBase)getAgent()).getPercepts("visibleEntity");
			for(String s : p.getValues())
			{
				StringTokenizer tk = new StringTokenizer(s);
				String name = tk.nextToken();
				String posT = tk.nextToken();
				if(name.equals(target))
				{
					Action act = follow(posT);
					if(act != null)
					{
						if(agent.isVerbose())
							agent.println("La cible est pursuivie");
						return act;
					}
					else
					{
						
						Chemin tmp = graph.pathTo(pos, posT);
						int size;
						if(tmp == null)
							size = tmp.getListNoeud().size();
						else
							size = 0;
						int range = Integer.parseInt(agent.getPercepts("visRange").getValues().get(0));
						if((size <= range) || size == 0)
						{
							if(agent.isVerbose())
								agent.println("Attaque de la cible");
							return Util.attackAction(target);
						}
						else
						{
							if(agent.isVerbose())
								agent.println("Approcher cible");
								return Util.gotoAction(tmp.getListNoeud().get(0));
						}
	
					}
						
				}
			}
			if(road == null)
			{
				target = null;
				return null;
			}
			if(road.getDernierNoeud().equals(pos))
			{
				target = null;
				((AgentSab)agent).setChemin(null);
				return null;
			}
			else if(road != null)
			{
				String dest = null;
				for(String s : road.getListNoeud())
				{
					if(s.equals(pos))
					{
						int ind = road.getListNoeud().indexOf(s);
						dest = road.getListNoeud().get(ind+1);
						break;
					}
				}
				if(dest != null)
					return Util.gotoAction(dest);
				else
				{
					if(agent.isVerbose())
						agent.println("Probleme pour atteindre la cible "+target );
					return null;
				}
			}
			
			
		}
		return null;
	}
	
	public Action follow(String posT)
	{
		String pos = ((AgentBase)getAgent()).getPercepts("position").getValues().get(0);
		Chemin ch = new Chemin();
		Graph graph = ((AgentSab)getAgent()).getGraph();
		ch = graph.pathTo(pos, posT);
		
		if(ch!= null)
		{
			if (ch.getListNoeud().size() > 1)
				return Util.gotoAction(ch.getListNoeud().get(0));
		}
		return null;
	}
}